package cn.wenhe9.novel.interceptor;

import cn.wenhe9.novel.auth.AuthStrategy;
import cn.wenhe9.novel.auth.UserHolder;
import cn.wenhe9.novel.constant.ApiRouterConsts;
import cn.wenhe9.novel.constant.SystemConfigConsts;
import cn.wenhe9.novel.exception.NovelException;
import cn.wenhe9.novel.result.ResultResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 认证 拦截器
 * 为了注入其它的 Spring beans，需要通过 @Component 注解将该拦截器注册到 Spring 上下文
 *
 * @author DuJinliang
 * 2022/5/18
 */
@Component
@RequiredArgsConstructor
public class AuthInterceptor implements HandlerInterceptor {

    private final Map<String, AuthStrategy> authStrategy;

    private final ObjectMapper objectMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取登录 JWT
        String token = request.getHeader(SystemConfigConsts.HTTP_AUTH_HEADER_NAME);

        // 获取请求的 URI
        String requestUri = request.getRequestURI();

        // 根据请求的 URI 得到认证策略/api/
        String authStrategyName = requestUri.substring(ApiRouterConsts.API_URL_PREFIX.length() + 1);
        authStrategyName = authStrategyName.substring(0,authStrategyName.indexOf("/"));
        authStrategyName = String.format("%sAuthStrategy",authStrategyName);

        // 开始认证
        try {
            authStrategy.get(authStrategyName).auth(token);
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }catch (NovelException exception){
            // 认证失败
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setContentType("application/json");
            response.getWriter().write(objectMapper.writeValueAsString(ResultResponse.fail(exception.getResultCodeEnum())));
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 清理当前线程保存的用户数据
        UserHolder.clear();
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
}
